package com.sc.nft.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.meta.component.base.api.CommonResult;
import com.meta.component.base.api.ResultCode;
import com.meta.push.plat.client.api.MetaPushPlatClient;
import com.meta.push.plat.client.enums.PushBusinessTypeEnum;
import com.meta.push.plat.client.enums.PushTypeEnum;
import com.meta.push.plat.client.req.PushMessageBodyRequest;
import com.meta.push.plat.client.req.PushMessageRequest;
import com.sc.nft.dao.*;
import com.sc.nft.dto.DrawPrizeDTO;
import com.sc.nft.dto.PushMessageExtendDTO;
import com.sc.nft.entity.*;
import com.sc.nft.entity.vo.*;
import com.sc.nft.enums.*;
import com.sc.nft.enums.task.DrawPriceTypeEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.helper.MessageQueueHelper;
import com.sc.nft.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RSet;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 质押任务(秘境)主表服务接口实现
 *
 * @author Sun
 * @description 由 Mybatisplus Code Generator 创建
 * @since 2023-06-12 15:36:35
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class PledgeTaskInfoServiceImpl implements PledgeTaskInfoService {
    private final PledgeTaskInfoDao pledgeTaskInfoDao;
    private final PledgeTaskVigorousCollectionService pledgeTaskVigorousCollectionService;
    private final PledgeTaskCollectionService pledgeTaskCollectionService;
    private final UserCollectionService userCollectionService;
    private final SecondCollectionConfigDao secondCollectionConfigDao;
    private final UserVigorousCollectionRecordsService userVigorousCollectionRecordsService;
    private final UserPledgeCollectionRecordsService userPledgeCollectionRecordsService;
    private final PledgeTaskRewardService pledgeTaskRewardService;
    private final UserVigorousRecordsDao userVigorousRecordsDao;
    private final TaskService taskService;
    private final MessageQueueHelper MessageQueueHelper;
    private final RedissonClient redissonClient;
    private final MetaPushPlatClient metaPushPlatClient;
    private final UserPushConfDao userPushConfDao;
    private final UserRelationPushCidDao userRelationPushCidDao;

    @Override
    public Page<AdminPagePledgeTaskVO> adminPagePledgeTask(String pledgeTaskName, Integer pageNo, Integer pageSize) {
        return pledgeTaskInfoDao.adminPagePledgeTask(pledgeTaskName, pageNo, pageSize);
    }


    @Override
    public void adminUpdateIsEnable(Long id, Boolean isEnable) {
        PledgeTaskInfo pledgeTaskInfo = pledgeTaskInfoDao.getById(id);
        Assert.notNull(pledgeTaskInfo, () -> new GlobalRunTimeException("质押任务不存在"));
        Assert.isFalse(pledgeTaskInfo.getIsEnable() == isEnable, () -> new GlobalRunTimeException("质押任务启用状态未改变"));
        Assert.isTrue(pledgeTaskInfoDao.updateIsEnableById(id, isEnable), () -> new GlobalRunTimeException("修改质押任务启用状态失败"));
    }

    @Override
    public void adminUpdatePledgeTaskIsSort(Long id, Integer sort) {
        PledgeTaskInfo pledgeTaskInfo = pledgeTaskInfoDao.getById(id);
        Assert.notNull(pledgeTaskInfo, () -> new GlobalRunTimeException("质押任务不存在"));
        Assert.isTrue(pledgeTaskInfoDao.adminUpdatePledgeTaskIsSort(id, sort), () -> new GlobalRunTimeException("修改质押任务排序失败"));
    }

    @Override
    public AdminPledgeTaskDetailsVO getAdminPledgeTaskDetails(Long id) {
        PledgeTaskInfo pledgeTaskInfo = pledgeTaskInfoDao.getById(id);
        Assert.notNull(pledgeTaskInfo, () -> new GlobalRunTimeException("质押任务不存在"));

        AdminPledgeTaskDetailsVO adminPledgeTaskDetailsVO = BeanUtil.copyProperties(pledgeTaskInfo, AdminPledgeTaskDetailsVO.class);
        //激活列表
        List<PledgeTaskVigorousCollection> pledgeTaskVigorousList = pledgeTaskVigorousCollectionService.getListByPledgeTaskId(id);
        adminPledgeTaskDetailsVO.setVigorousCollectionList(BeanUtil.copyToList(pledgeTaskVigorousList, AdminPledgeTaskVigorousCollectionDetailsVO.class));

        //质押列表
        adminPledgeTaskDetailsVO.setPledgeTaskCollectionList(pledgeTaskCollectionService.adminGetListByPledgeTaskId(id));
        return adminPledgeTaskDetailsVO;
    }

    @Override
    public void updatePledgeTaskJoinCount(Long id, Integer joinCount) {
        PledgeTaskInfo pledgeTaskInfo = pledgeTaskInfoDao.getById(id);
        Assert.notNull(pledgeTaskInfo, () -> new GlobalRunTimeException("质押任务不存在"));
        Assert.isTrue(pledgeTaskInfoDao.updatePledgeTaskJoinCount(id, joinCount), () -> new GlobalRunTimeException("修改质押任务排序失败"));
    }

    @Override
    public Page<SecretAreaPageVO> secretAreaPage(UserInfo user, Integer pageNo, Integer pageSize) {
        Page<SecretAreaPageVO> page = pledgeTaskInfoDao.secretAreaPage(pageNo, pageSize);
        DateTime now = DateTime.now();
        for (SecretAreaPageVO record : page.getRecords()) {
            record.setBeginTime(record.getPledgeTaskBeginTime());

            //判断是否开始
            if (now.isBefore(record.getPledgeTaskBeginTime())) {
                record.setIsBegin(0);
            } else if (now.isAfter(record.getPledgeTaskBeginTime()) && now.isBefore(record.getPledgeTaskEndTime())) {
                record.setIsBegin(1);
            } else if (now.isAfter(record.getPledgeTaskEndTime())) {
                record.setIsBegin(2);
            }
            //激活状态
            Integer count = userVigorousCollectionRecordsService.getOneByUserIdAndPledgeTaskIdAndVigorousStatus(user.getId(), record.getId(), VigorousStatusEnum.ACTIVATED);
            record.setVigorousStatus(count.intValue() > 0 ? Boolean.TRUE : Boolean.FALSE);

            //处理标签
            record.setLabelList(Lists.newArrayList(record.getLabel().split(",")));
        }
        return page;
    }

    @Override
    public SecretAreaVigorousDetailsVO secretAreaVigorousDetails(Long id, UserInfo user) {
        PledgeTaskInfo pledgeTaskInfo = pledgeTaskInfoDao.getById(id);
        Assert.notNull(pledgeTaskInfo, () -> new GlobalRunTimeException("秘境不存在"));

        SecretAreaVigorousDetailsVO secretAreaVigorousDetailsVO = BeanUtil.copyProperties(pledgeTaskInfo, SecretAreaVigorousDetailsVO.class);
        secretAreaVigorousDetailsVO.setPledgeTaskId(pledgeTaskInfo.getId());
        //校验时间
        DateTime now = DateTime.now();
        Integer status = 0;
        if (now.isBefore(pledgeTaskInfo.getPledgeTaskBeginTime())) {
            status = 1;
        }

        if (now.after(pledgeTaskInfo.getPledgeTaskEndTime())) {
            status = 2;
        }

        //校验是否已经激活
        UserVigorousRecords userVigorousRecords = userVigorousCollectionRecordsService.getOneByPledgeTaskIdAndUserId(user.getId(), pledgeTaskInfo.getId(), VigorousStatusEnum.ACTIVATED);
        Assert.isTrue(ObjectUtil.isNull(userVigorousRecords), () -> new GlobalRunTimeException("请勿重复激活"));

        List<PledgeTaskVigorousCollection> vigorousCollectionList = pledgeTaskVigorousCollectionService.getListByPledgeTaskId(pledgeTaskInfo.getId());
        Assert.isTrue(vigorousCollectionList.size() > 0, () -> new GlobalRunTimeException("秘籍激活任务不存在"));

        ArrayList<PledgeTaskVigorousCollectionVO> vigorousCollectionVOList = Lists.newArrayList();
        for (PledgeTaskVigorousCollection pledgeTaskVigorousCollection : vigorousCollectionList) {
            PledgeTaskVigorousCollectionVO vigorousCollectionVO = BeanUtil.copyProperties(pledgeTaskVigorousCollection, PledgeTaskVigorousCollectionVO.class);
            vigorousCollectionVO.setPledgeTaskCollectionId(pledgeTaskVigorousCollection.getId());
            //用户持有数量
            vigorousCollectionVO.setHoldCount(userCollectionService.getIsContainsAndIsHoldAndIsOpenAndOnConsignByCollectionId(pledgeTaskVigorousCollection.getCollectionId(), user.getId()));
            vigorousCollectionVO.setIsSatisfy(Boolean.TRUE);
            //如果持有数量为0 或者持有数量小于激活数量
            if (vigorousCollectionVO.getHoldCount() <= 0 || vigorousCollectionVO.getHoldCount() < pledgeTaskVigorousCollection.getVigorousCount()) {
                //某个藏品是否满足条件
                vigorousCollectionVO.setIsSatisfy(Boolean.FALSE);
                //获取二级市场配置
                SecondCollectionConfig secondCollectionConfig = secondCollectionConfigDao.getByCollectionIdAndMarketType(pledgeTaskVigorousCollection.getCollectionId(), MarketTypeEnum.FREE_MARKET);
                vigorousCollectionVO.setSecondCollectionConfigId(ObjectUtil.isNull(secondCollectionConfig) ? 0L : secondCollectionConfig.getId());
            }
            vigorousCollectionVOList.add(vigorousCollectionVO);
        }


        if (status == 0) {
            //满足条件的集合
            List<Boolean> collect = vigorousCollectionVOList.stream().map(PledgeTaskVigorousCollectionVO::getIsSatisfy).collect(Collectors.toList());
            if (pledgeTaskInfo.getActivationCondition() == PledgeTaskActivationCondition.HOLD_SIMULTANEOUSLY && collect.contains(Boolean.FALSE)) {
                //同时持有 如果有一个不满足条件 就不可以激活
                status = 3;

            } else if (pledgeTaskInfo.getActivationCondition() == PledgeTaskActivationCondition.HOLD_AT_WILL && !collect.contains(Boolean.TRUE)) {
                //持有任意一个  如果其中一个满足条件 就可以激活
                status = 3;
            }
        }

        secretAreaVigorousDetailsVO.setStatus(status);
        secretAreaVigorousDetailsVO.setVigorousCollectionList(vigorousCollectionVOList);
        return secretAreaVigorousDetailsVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void vigorousSecretArea(UserInfo user, Long pledgeTaskId, List<VigorousCollectionVO> userVigorousCollectionList) {
        //校验质押任务
        PledgeTaskInfo pledgeTaskInfo = pledgeTaskInfoDao.getById(pledgeTaskId);
        Assert.notNull(pledgeTaskInfo, () -> new GlobalRunTimeException("秘境不存在"));


        //校验时间
        DateTime now = DateTime.now();
        if (now.isBefore(pledgeTaskInfo.getPledgeTaskBeginTime())) {
            throw new GlobalRunTimeException("秘境未到开启时间");
        }

        if (now.after(pledgeTaskInfo.getPledgeTaskEndTime())) {
            throw new GlobalRunTimeException("秘境已经结束");
        }

        //秘境关联的激活条件
        List<PledgeTaskVigorousCollection> vigorousCollectionList = pledgeTaskVigorousCollectionService.getListByPledgeTaskId(pledgeTaskInfo.getId());
        Assert.isTrue(vigorousCollectionList.size() > 0, () -> new GlobalRunTimeException("秘籍激活任务不存在"));

        //校验是否已经激活
        UserVigorousRecords checkUserVigorousRecords = userVigorousCollectionRecordsService.getOneByPledgeTaskIdAndUserId(user.getId(), pledgeTaskInfo.getId(), VigorousStatusEnum.ACTIVATED);
        Assert.isTrue(ObjectUtil.isNull(checkUserVigorousRecords), () -> new GlobalRunTimeException("请勿重复激活"));

        Integer vigorousCount = 0;

        UserVigorousRecords userVigorousRecords = new UserVigorousRecords();
        userVigorousRecords.setUserId(user.getId());
        userVigorousRecords.setPledgeTaskId(pledgeTaskInfo.getId());
        userVigorousRecords.setPledgeTaskName(pledgeTaskInfo.getPledgeTaskName());
        userVigorousRecords.setVigorousTime(DateTime.now());
        userVigorousRecords.setVigorousStatus(VigorousStatusEnum.ACTIVATED);
        userVigorousRecords.insert();

        //校验同时持有
        if (pledgeTaskInfo.getActivationCondition() == PledgeTaskActivationCondition.HOLD_SIMULTANEOUSLY) {
            Assert.isTrue(vigorousCollectionList.size() == userVigorousCollectionList.size(), () -> new GlobalRunTimeException("激活任务需要同时满足"));

            //所需的激活任务id
            List<Long> vigorousIds = vigorousCollectionList.stream().map(PledgeTaskVigorousCollection::getId).collect(Collectors.toList());
            //升序
            Collections.sort(vigorousIds);

            //传入的激活任务id
            List<Long> collect = userVigorousCollectionList.stream().map(VigorousCollectionVO::getPledgeTaskCollectionId).collect(Collectors.toList());
            //升序
            Collections.sort(collect);

            //校验两个集合的每个位置的值是否相等
            Assert.isTrue(Arrays.equals(vigorousIds.toArray(), collect.toArray()), () -> new GlobalRunTimeException("激活任务需要同时满足"));

            //校验每个藏品的数量是否满足
            for (VigorousCollectionVO vigorousCollectionVO : userVigorousCollectionList) {
                PledgeTaskVigorousCollection pledgeTaskVigorousCollection = pledgeTaskVigorousCollectionService.getById(vigorousCollectionVO.getPledgeTaskCollectionId());
                Assert.isTrue(ObjectUtil.isNotNull(pledgeTaskVigorousCollection), () -> new GlobalRunTimeException("秘境激活任务不存在"));

                //传入的藏品集合id
                List<Long> userCollectionIdList = vigorousCollectionVO.getUserCollectionIdList();
                Assert.isTrue(userCollectionIdList.size() > 0, () -> new GlobalRunTimeException(StrUtil.format("激活任务所需{}的数量不足", pledgeTaskVigorousCollection.getFirstTitle())));
                //根据用户id 和藏品id 和用户持有的藏品集合id 查询用户藏品集合
                List<UserCollection> userCollections = userCollectionService.getListByUserIdAndCollectionIdAndIds(user.getId(), pledgeTaskVigorousCollection.getCollectionId(), userCollectionIdList);
                //数量不匹配
                Assert.isTrue(pledgeTaskVigorousCollection.getVigorousCount() == userCollections.size(), () -> new GlobalRunTimeException(StrUtil.format("激活任务所需{}的数量与传入数量不匹配", pledgeTaskVigorousCollection.getFirstTitle())));

                //冻结藏品
                for (UserCollection userCollection : userCollections) {
                    Assert.isTrue(userCollectionService.updateFreezingStatusById(userCollection.getId(), UserCollectionFreezingStatusEnum.VERY_ACTIVE), () -> new GlobalRunTimeException("激活失败,请稍后重试"));

                    UserVigorousCollectionRecords userVigorousCollectionRecords = new UserVigorousCollectionRecords();
                    userVigorousCollectionRecords.setUserId(user.getId());
                    userVigorousCollectionRecords.setCollectionId(userCollection.getCollectionId());
                    userVigorousCollectionRecords.setPledgeTaskVigorousCollectionId(pledgeTaskVigorousCollection.getId());
                    userVigorousCollectionRecords.setUserVigorousRecordsId(userVigorousRecords.getId());
                    userVigorousCollectionRecords.setUserCollectionId(userCollection.getId());
                    userVigorousCollectionRecords.setFirstTitle(userCollection.getFirstTitle());
                    userVigorousCollectionRecords.setCollectionImage(userCollection.getCollectionImage());
                    userVigorousCollectionRecords.setVigorousStatus(VigorousStatusEnum.ACTIVATED);
                    userVigorousCollectionRecords.insert();
                }
                vigorousCount = userCollections.size() + vigorousCount;
            }

        } else if (pledgeTaskInfo.getActivationCondition() == PledgeTaskActivationCondition.HOLD_AT_WILL) {
            //传入的激活信息
            Assert.isTrue(userVigorousCollectionList.size() == 1, () -> new GlobalRunTimeException("激活任务只需满足其中一个即可"));
            VigorousCollectionVO vigorousCollectionVO = userVigorousCollectionList.get(0);
            //激活条件
            PledgeTaskVigorousCollection pledgeTaskVigorousCollection = pledgeTaskVigorousCollectionService.getByIdAndPledgeTaskId(vigorousCollectionVO.getPledgeTaskCollectionId(), pledgeTaskInfo.getId());
            Assert.isTrue(ObjectUtil.isNotNull(pledgeTaskVigorousCollection), () -> new GlobalRunTimeException("秘境激活任务不存在"));

            List<Long> userCollectionIdList = vigorousCollectionVO.getUserCollectionIdList();
            //根据用户id 和藏品id 和用户持有的藏品集合id 查询用户藏品集合
            List<UserCollection> userCollections = userCollectionService.getListByUserIdAndCollectionIdAndIds(user.getId(), pledgeTaskVigorousCollection.getCollectionId(), userCollectionIdList);
            //数量不匹配
            Assert.isTrue(pledgeTaskVigorousCollection.getVigorousCount() == userCollections.size(), () -> new GlobalRunTimeException(StrUtil.format("激活任务所需{}的数量与传入数量不匹配", pledgeTaskVigorousCollection.getFirstTitle())));

            //激活数量
            vigorousCount = pledgeTaskVigorousCollection.getVigorousCount();
            //冻结藏品
            for (UserCollection userCollection : userCollections) {
                Assert.isTrue(userCollectionService.updateFreezingStatusById(userCollection.getId(), UserCollectionFreezingStatusEnum.VERY_ACTIVE), () -> new GlobalRunTimeException("激活失败,请稍后重试"));

                UserVigorousCollectionRecords userVigorousCollectionRecords = new UserVigorousCollectionRecords();
                userVigorousCollectionRecords.setUserId(user.getId());
                userVigorousCollectionRecords.setCollectionId(userCollection.getCollectionId());
                userVigorousCollectionRecords.setUserVigorousRecordsId(userVigorousRecords.getId());
                userVigorousCollectionRecords.setPledgeTaskVigorousCollectionId(pledgeTaskVigorousCollection.getId());
                userVigorousCollectionRecords.setUserCollectionId(userCollection.getId());
                userVigorousCollectionRecords.setFirstTitle(userCollection.getFirstTitle());
                userVigorousCollectionRecords.setCollectionImage(userCollection.getCollectionImage());
                userVigorousCollectionRecords.setVigorousStatus(VigorousStatusEnum.ACTIVATED);
                userVigorousCollectionRecords.insert();
            }

        }
        //修改激活数量
        Assert.isTrue(userVigorousRecordsDao.updateVigorousCountById(userVigorousRecords.getId(), vigorousCount), () -> new GlobalRunTimeException("激活失败,请稍后重试"));

        //参数任务+1
        Assert.isTrue(pledgeTaskInfoDao.updateJoinCount(pledgeTaskId), () -> new GlobalRunTimeException("激活失败,请稍后重试"));
    }

    @Override
    public List<PledgeTaskCollectionVO> secretAreaCollectionDetails(Long id, UserInfo user) {
        PledgeTaskInfo pledgeTaskInfo = pledgeTaskInfoDao.getById(id);
        Assert.notNull(pledgeTaskInfo, () -> new GlobalRunTimeException("秘境不存在"));

        //校验时间
        DateTime now = DateTime.now();
        if (now.isBefore(pledgeTaskInfo.getPledgeTaskBeginTime())) {
            throw new GlobalRunTimeException("秘境未到开启时间");
        }

        if (now.after(pledgeTaskInfo.getPledgeTaskEndTime())) {
            throw new GlobalRunTimeException("秘境已经结束");
        }


        //校验是否已经激活
        UserVigorousRecords checkUserVigorousRecords = userVigorousCollectionRecordsService.getOneByPledgeTaskIdAndUserId(user.getId(), pledgeTaskInfo.getId(), VigorousStatusEnum.ACTIVATED);
        Assert.isTrue(ObjectUtil.isNotNull(checkUserVigorousRecords), () -> new GlobalRunTimeException("激活秘境未激活"));

        return pledgeTaskCollectionService.getListByPledgeTaskId(user, pledgeTaskInfo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchPledgeSecret(UserInfo user, Long pledgeTaskId, Long pledgeTaskCollectionId, List<Long> userCollectionIdList, Integer count) {
        //校验质押任务
        PledgeTaskInfo pledgeTaskInfo = pledgeTaskInfoDao.getById(pledgeTaskId);
        Assert.notNull(pledgeTaskInfo, () -> new GlobalRunTimeException("秘境不存在"));

        //校验时间
        DateTime now = DateTime.now();
        if (now.isBefore(pledgeTaskInfo.getPledgeTaskBeginTime())) {
            throw new GlobalRunTimeException("秘境未到开启时间");
        }

        if (now.after(pledgeTaskInfo.getPledgeTaskEndTime())) {
            throw new GlobalRunTimeException("秘境已经结束");
        }

        UserVigorousRecords checkUserVigorousRecords = userVigorousCollectionRecordsService.getOneByPledgeTaskIdAndUserId(user.getId(), pledgeTaskInfo.getId(), VigorousStatusEnum.ACTIVATED);
        Assert.isTrue(ObjectUtil.isNotNull(checkUserVigorousRecords), () -> new GlobalRunTimeException("秘境未激活"));

        if (!pledgeTaskInfo.getIsRepeatedly()) {
            Integer pledgeCount = userPledgeCollectionRecordsService.getCountByUserIdAndPledgeTaskIdAndPledgeTaskCollectionIdAndStatus(user.getId(), pledgeTaskInfo.getId(), pledgeTaskCollectionId, PledgeStatusEnum.IN_PLEDGE);
            Assert.isFalse(pledgeCount > 0, () -> new GlobalRunTimeException("此秘境只能质押一次"));
        }

        //校验质押条件
        PledgeTaskCollection pledgeTaskCollection = pledgeTaskCollectionService.getOneByPledgeTaskIdAndId(pledgeTaskId, pledgeTaskCollectionId);
        Assert.isTrue(ObjectUtil.isNotNull(pledgeTaskCollection), () -> new GlobalRunTimeException("秘境质押条件不正确"));

        int collectionPledgeCount = pledgeTaskCollection.getPledgeCount() * count;
        //质押藏品的数量
        List<UserCollection> userCollections = new ArrayList<>();
        //版本兼容 获取用户藏品集合
        if (count.equals(0)) {
            userCollections = userCollectionService.getListByUserIdAndCollectionIdAndCount(user.getId(), pledgeTaskCollection.getCollectionId(), userCollectionIdList);
        } else {
            userCollections = userCollectionService.getListByUserIdAndCollectionIdAndCount(user.getId(), pledgeTaskCollection.getCollectionId(), collectionPledgeCount);
        }
        //任务所需数量 * 质押份数
        Assert.isTrue(collectionPledgeCount == userCollections.size(), () -> new GlobalRunTimeException(StrUtil.format("质押所需{}的数量与传入数量不匹配", pledgeTaskCollection.getFirstTitle())));
        //质押奖励列表
        List<PledgeTaskReward> pledgeRewardList = pledgeTaskRewardService.getListByPledgeTaskIdAndPledgeTaskCollectionId(pledgeTaskId, pledgeTaskCollectionId);
        Assert.isTrue(pledgeRewardList.size() > 0, () -> new GlobalRunTimeException("质押奖励不存在"));

        List<List<UserCollection>> userCollectionLists = CollUtil.split(userCollections, pledgeTaskCollection.getPledgeCount());
        Assert.isTrue(userCollectionLists.size() > 0, () -> new GlobalRunTimeException(StrUtil.format("质押所需{}的数量与传入数量不匹配", pledgeTaskCollection.getFirstTitle())));
        UserVigorousRecords userVigorousRecords = userVigorousCollectionRecordsService.getOneByPledgeTaskIdAndUserId(user.getId(), pledgeTaskId, VigorousStatusEnum.ACTIVATED);
        for (List<UserCollection> userCollectionList : userCollectionLists) {
            pledgeSecretArea(user.getId(), pledgeTaskInfo, pledgeTaskCollection, pledgeRewardList, userCollectionList, userVigorousRecords.getId());
        }

    }


    @Transactional(rollbackFor = Exception.class)
    public void pledgeSecretArea(Long userId, PledgeTaskInfo pledgeTaskInfo, PledgeTaskCollection pledgeTaskCollection, List<PledgeTaskReward> pledgeRewardList, List<UserCollection> userCollections, Long userVigorousRecordsId) {
        UserPledgeRecords userPledgeRecords = new UserPledgeRecords();
        userPledgeRecords.setPledgeTaskId(pledgeTaskInfo.getId());
        userPledgeRecords.setPledgeTaskName(pledgeTaskInfo.getPledgeTaskName());
        userPledgeRecords.setPledgeTaskCollectionId(pledgeTaskCollection.getId());
        //奖励的ids集合
        userPledgeRecords.setPledgeTaskRewardIds(pledgeRewardList.stream().map(PledgeTaskReward::getId).map(String::valueOf).collect(Collectors.joining(",")));
        userPledgeRecords.setUserId(userId);
        userPledgeRecords.setUserVigorousRecordsId(userVigorousRecordsId);
        userPledgeRecords.setPledgeStatus(PledgeStatusEnum.IN_PLEDGE);
        userPledgeRecords.setCompleteTime(DateUtil.offset(DateTime.now(), DateField.HOUR, pledgeTaskCollection.getPledgeTime()));
        userPledgeRecords.setPledgeCount(pledgeTaskCollection.getPledgeCount());
        userPledgeRecords.setCollectionImage(pledgeTaskCollection.getCollectionImage());
        userPledgeRecords.setFirstTitle(pledgeTaskCollection.getFirstTitle());
        userPledgeRecords.setRewardStatus(RewardStatusEnum.NOT_ISSUED);
        userPledgeRecords.insert();


        for (UserCollection userCollection : userCollections) {
            Assert.isTrue(userCollectionService.updateFreezingStatusById(userCollection.getId(), UserCollectionFreezingStatusEnum.PRESSING), () -> new GlobalRunTimeException("激活失败,请稍后重试"));

            UserPledgeCollectionRecords userPledgeCollectionRecords = new UserPledgeCollectionRecords();
            userPledgeCollectionRecords.setUserPledgeRecordsId(userPledgeRecords.getId());
            userPledgeCollectionRecords.setUserId(userId);
            userPledgeCollectionRecords.setUserCollectionId(userCollection.getId());
            userPledgeCollectionRecords.setCollectionId(userCollection.getCollectionId());
            userPledgeCollectionRecords.setFirstTitle(userCollection.getFirstTitle());
            userPledgeCollectionRecords.setCollectionImage(userCollection.getCollectionImage());
            userPledgeCollectionRecords.setCompleteTime(userPledgeRecords.getCompleteTime());
            userPledgeCollectionRecords.setPledgeStatus(PledgeStatusEnum.IN_PLEDGE);
            userPledgeCollectionRecords.insert();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void quitSecretArea(UserInfo user, Long pledgeTaskId) {
        //校验质押任务
        PledgeTaskInfo pledgeTaskInfo = pledgeTaskInfoDao.getById(pledgeTaskId);
        Assert.notNull(pledgeTaskInfo, () -> new GlobalRunTimeException("秘境不存在"));

        UserVigorousRecords userVigorousRecords = userVigorousCollectionRecordsService.getOneByPledgeTaskIdAndUserId(user.getId(), pledgeTaskId, VigorousStatusEnum.ACTIVATED);
        Assert.isTrue(ObjectUtil.isNotNull(userVigorousRecords), () -> new GlobalRunTimeException("未激活秘境"));

        Integer userPledgeCollectionCount = userPledgeCollectionRecordsService.getCountByUserIdAndPledgeTaskIdAndStatus(user.getId(), pledgeTaskId, PledgeStatusEnum.IN_PLEDGE);
        Assert.isTrue(userPledgeCollectionCount == 0, () -> new GlobalRunTimeException("挖宝中,无法退出"));


        Assert.isTrue(userVigorousRecordsDao.updateVigorousStatusById(userVigorousRecords.getId(), VigorousStatusEnum.RETURNED), () -> new GlobalRunTimeException("退出失败,请稍后重试"));
        List<UserVigorousCollectionRecords> userVigorousCollectionRecordsList = userVigorousCollectionRecordsService.getListByUserVigorousRecordsId(userVigorousRecords.getId(), VigorousStatusEnum.ACTIVATED);
        for (UserVigorousCollectionRecords userVigorousCollectionRecords : userVigorousCollectionRecordsList) {
            Assert.isTrue(userCollectionService.updateFreezingStatusById(userVigorousCollectionRecords.getUserCollectionId(), UserCollectionFreezingStatusEnum.NORMAL), () -> new GlobalRunTimeException("退出失败,请稍后重试"));
        }
    }

    @Override
    public Page<VigorousSecretAreaPageVO> vigorousSecretAreaPage(UserInfo user, Integer pageNo, Integer pageSize) {
        return userVigorousCollectionRecordsService.getPageVigorousSecretAreaRecordsByUserId(user.getId(), pageNo, pageSize);
    }

    @Override
    public VigorousSecretAreaDetailsVO vigorousSecretAreaDetails(UserInfo user, Long pledgeTaskId, Long userVigorousRecordsId) {
        return userVigorousCollectionRecordsService.vigorousSecretAreaDetails(user, pledgeTaskId, userVigorousRecordsId);
    }

    @Override
    public Page<PledgeSecretAreaPageVO> pledgeSecretAreaPage(UserInfo user, Long pledgeTaskId, Integer pageNo, Integer pageSize) {
        return userPledgeCollectionRecordsService.pledgeSecretAreaPage(user, pledgeTaskId, pageNo, pageSize);
    }

    @Override
    public PledgeSecretAreaDetailsVO pledgeSecretAreaDetails(UserInfo user, Long pledgeTaskId, Long userPledgeRecordsId) {
        return userPledgeCollectionRecordsService.pledgeSecretAreaDetails(user, pledgeTaskId, userPledgeRecordsId);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void pledgeTaskAward(UserPledgeRecords userPledgeRecords) {
        log.info(StrUtil.format("质押任务奖励发放开始,用户id:{}", userPledgeRecords.getUserId()));
        log.info(StrUtil.format("质押任务名称:{}", userPledgeRecords.getPledgeTaskName()));
        log.info(StrUtil.format("质押记录id:{}", userPledgeRecords.getId()));
        log.info(StrUtil.format("执行时间 MQ:{}", DateUtil.formatDateTime(new Date())));

        List<DrawPrizeDTO> prizeDTOS = pledgeTaskRewardService.getDrawPrizeDTOListByPledgeTaskCollectionIdAndPledgeTaskId(userPledgeRecords.getPledgeTaskId(), userPledgeRecords.getPledgeTaskCollectionId());
        Assert.isTrue(CollUtil.isNotEmpty(prizeDTOS), () -> new GlobalRunTimeException("奖励不存在"));
        taskService.addDrawPrize(userPledgeRecords.getUserId(), userPledgeRecords.getPledgeTaskId(), userPledgeRecords.getId(), userPledgeRecords.getPledgeTaskName(), prizeDTOS, DrawPriceTypeEnum.PLEDGE);
        //更新奖励状态为已发放
        Assert.isTrue(userPledgeCollectionRecordsService.updateSuccessForPledgeStatusById(userPledgeRecords.getId()), () -> new GlobalRunTimeException("奖励发放失败"));
        //获取质押的用户藏品明细
        List<UserPledgeCollectionRecords> userPledgeCollectionRecordsList = userPledgeCollectionRecordsService.getListByUserIdAndUserPledgeRecordsIdAndPledgeStatus(userPledgeRecords.getUserId(), userPledgeRecords.getId(), PledgeStatusEnum.IN_PLEDGE);
        Assert.isTrue(CollUtil.isNotEmpty(userPledgeCollectionRecordsList), () -> new GlobalRunTimeException("奖励列表为空"));
        //批量释放用户藏品
        Assert.isTrue(userCollectionService.updateFreezingStatusByIds(userPledgeCollectionRecordsList.stream().map(UserPledgeCollectionRecords::getUserCollectionId).collect(Collectors.toList()), UserCollectionFreezingStatusEnum.NORMAL), () -> new GlobalRunTimeException("用户藏品释放失败"));
        //批量修改用户质押明细表质押状态为已结束
        Assert.isTrue(userPledgeCollectionRecordsService.updatePledgeStatusByUserPledgeRecordsId(userPledgeRecords.getId(), PledgeStatusEnum.END_OF_PLEDGE), () -> new GlobalRunTimeException("修改用户质押藏品明细表失败!"));
        //推送消息
        String redissonKey = RedisKeyEnum.PLEDGE_PUSH.getKey() + userPledgeRecords.getPledgeTaskId() + "_" + userPledgeRecords.getUserId();
        log.info(StrUtil.format("质押任务奖励推送缓存主键:{}", redissonKey));
        RSet<Boolean> set = redissonClient.getSet(redissonKey);
        log.info(StrUtil.format("质押任务奖励推送缓存值:{}", JSON.toJSONString(set)));
        if (CollectionUtil.isEmpty(set)) {
            if (set.add(true)) {
                set.expire(1L, TimeUnit.HOURS);
                UserPushConf userPushConf = userPushConfDao.getByUserId(userPledgeRecords.getUserId());
                if (Objects.nonNull(userPushConf)) {
                    if (!userPushConf.getEnablePledgeTaskPush()) {
                        return;
                    }
                }
                UserRelationPushCid userRelationPushCid = userRelationPushCidDao.getByUserId(userPledgeRecords.getUserId());
                if (Objects.isNull(userRelationPushCid)) {
                    return;
                }
                pushPledgeMessage(userPledgeRecords.getId(), userRelationPushCid.getCid(), userPledgeRecords.getPledgeTaskName());
            }
        }
    }

    /**
     * 推送秘境消息
     */
    private void pushPledgeMessage(Long businessId, String cid, String pledgeTaskName) {
        List<String> cidList = new ArrayList<>();
        cidList.add(cid);
        PushMessageRequest pushMessageRequest = new PushMessageRequest();
        pushMessageRequest.setPushBusinessType(PushBusinessTypeEnum.ELSE_PUSH);
        pushMessageRequest.setSource(PushSourceEnum.METAGO.getCode());
        pushMessageRequest.setPushType(PushTypeEnum.SINGLE_PUSH_BY_CID);
        pushMessageRequest.setCid(cidList);
        PushMessageBodyRequest pushMessageBodyRequest = new PushMessageBodyRequest();
        pushMessageBodyRequest.setTitle("您订阅的秘境之旅通知");
        pushMessageBodyRequest.setContent(StrUtil.format("您参与的{}，奖励已到账，具体奖励请登录平台查看", pledgeTaskName));
        pushMessageBodyRequest.setUrl("https://www.gometa.com.cn/officalH5");
        pushMessageRequest.setBody(pushMessageBodyRequest);
        PushMessageExtendDTO pushMessageExtendDTO = new PushMessageExtendDTO();
        pushMessageExtendDTO.setBusinessId(businessId);
        pushMessageExtendDTO.setBusinessObject(PushMessageExtendBusinessEnum.USER_PLEDGE_RECORDS.getCode());
        pushMessageExtendDTO.setBusinessDesc("秘境任务");
        pushMessageRequest.setExtend(JSON.toJSONString(pushMessageExtendDTO));
        CommonResult commonResult = metaPushPlatClient.pushMessage(pushMessageRequest);
        if (!Objects.equals(ResultCode.SUCCESS.getCode(), commonResult.getCode())) {
            log.error(commonResult.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePledgeTaskAwardStatus(UserPledgeRecords userPledgeRecords) {
        //更新奖励状态为已发放
        if (userPledgeCollectionRecordsService.updatePledgeStatusAndRewardStatusById(userPledgeRecords.getId(), PledgeStatusEnum.IN_PLEDGE, PledgeStatusEnum.END_OF_PLEDGE, RewardStatusEnum.DISTRIBUTING)) {
            //通过MQ发放奖励
            MessageQueueHelper.sendMessage(MessageTopic.PLEDGE_TASK_AWARD_TOPIC, userPledgeRecords);
        } else {
            throw new GlobalRunTimeException(StrUtil.format("秘境质押发放MQ失败,质押记录id:{}", userPledgeRecords.getId()));
        }
    }

    @Override
    public PledgeSecretMaxCount pledgeSecretMaxCount(Long pledgeTaskId, Long collectionId, UserInfo user) {
        PledgeTaskCollection pledgeTaskCollection = pledgeTaskCollectionService.getOneByPledgeTaskIdAndCollectionId(pledgeTaskId, collectionId);
        //指定秘境用户持有的所有藏品
        //排除锁仓中，挂售中，仅熔炼，挖宝中，质押中，上链中，etc?
        Integer pledgeSecretByUserIdAndCollection = userCollectionService.getPledgeSecretByUserIdAndCollectionId(user.getId(), collectionId);
        PledgeSecretMaxCount pledgeSecretMaxCount = new PledgeSecretMaxCount();
        List<UserCollection> userCollections = userCollectionService.pledgeSecretMaxCount(user.getId(), collectionId);
        pledgeSecretMaxCount.setPledgeSecretMaxCount(0);
        if (ObjectUtil.isNotNull(userCollections) && !Convert.toBigDecimal(pledgeTaskCollection.getPledgeCount()).equals(BigDecimal.ZERO)) {
            pledgeSecretMaxCount.setPledgeSecretMaxCount(Convert.toInt(Convert.toBigDecimal(userCollections.size()).divide(Convert.toBigDecimal(pledgeTaskCollection.getPledgeCount()), 0, BigDecimal.ROUND_DOWN).stripTrailingZeros()));
        }
        pledgeSecretMaxCount.setPledgeSecretSurplusCount(pledgeSecretByUserIdAndCollection);
        pledgeSecretMaxCount.setCollectionImage(pledgeTaskCollection.getCollectionImage());
        return pledgeSecretMaxCount;
    }

}